package com.corpgovernment.common.requestprocess;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.corpgovernment.common.utils.Null;
import com.ctrip.corp.obt.metric.Metrics;
import com.google.common.collect.Maps;

/**
 * 
 * @author dlz
 * @since 2023/12/6
 */
public final class MetricUtil {

    private MetricUtil() {}

    /**
     * 用此工具类主要为了解决埋点tag时key为null会报错的问题，会将null默认转为""
     * 
     * @param title 要写入clog的title
     */
    public static PrometheusMetricContext build(String title) {
        return new PrometheusMetricContext(title);
    }

    /**
     * 一条待埋点的普罗米修斯内容
     */
    public final static class PrometheusMetricContext {

        /**
         * 用于埋点的指标名
         */
        private final String title;

        /**
         * 埋点tag
         */
        private final Map<String, String> tags;

        private PrometheusMetricContext(String title) {
            this.title = title;
            this.tags = new HashMap<>();
        }

        /**
         * 通过timer方式记录指标
         *
         * @param duration 指标要记录的耗时(单位毫秒)
         */
        public void recordByTimer(int duration) {
            Metrics.REGISTRY.timer(Metrics.REGISTRY.createId(title).withTags(acquireMetricTag())).record(duration,
                TimeUnit.MILLISECONDS);
        }

        /**
         * 为这条日志添加一个tag
         */
        public PrometheusMetricContext tag(String key, String val) {
            tags.put(key, val);
            return this;
        }

        /**
         * 为这条日志添加多条tag
         */
        public PrometheusMetricContext tag(Map<String, String> tags) {
            this.tags.putAll(tags);
            return this;
        }

        /**
         * 为这条日志添加一个tag，val会用String.valueOf转为string
         */
        public PrometheusMetricContext tagAutoString(String key, Object val) {
            return tag(key, Null.or(val, String::valueOf));
        }

        /**
         * 获取埋点的tag
         */
        private Map<String, String> acquireMetricTag() {
            Map<String, String> metricTags = Maps.newHashMapWithExpectedSize(tags.size());
            tags.forEach((k, v) -> metricTags.put(k, Null.or(v, "")));
            return metricTags;
        }
    }
}
